home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_oth
/
tpcalc
/
tpcalc.pro
Wrap
Text File
|
1986-06-09
|
9KB
|
365 lines
/* TPCALC.PRO */
/* Copyright Craig Fleming, 1986. Rights granted for all */
/* not-for-profit usage and distribution. */
/* This Program takes advantage of the scratchpad memory routines
introduced in SCRTCH.PRO to implement a four register RPN calculator.
RPN is Reverse Polish Notation (of course), the same scheme used for HP
Calculators. Operations are performed on a four register stack. There
is also a fifth stack (not shown) which captures entries popped out of
stack four, and pushes them back again when the register stacks drop.
Total time to implement the calculator was about 4 hours, so it
may not be as elegant as possible. Even so it provides an impressive
display of Turbo Prolog's power. Improvements and Enhancements are
encouraged. For example, add macro programming capabilities to attach
special function key definitions.
A word of philosophy: Prolog's real power lies in its symbolic
processing capabilities. If you want to calculate heat flux across
a pipe with liquid flowing through it -- choose Fortran or Pascal.
It's just nice to know that you can crunch numbers if and when the
need arises. By the way Jerrold Kaplan of Lotus Development (quoted
in Byte 5/86) argues that spreadsheets are actually "object oriented
declarative programming languages". Interesting. */
domains
name = symbol
database
sp(name,real)
predicates
/* The basic scratchpad memory routines. Their names
describe their functions. */
remember(name,real)
recall(name,real)
forget(name)
replace(name,real)
/* The calculator engine */
process
action(real,string,string)
start
/* Various Utilities */
set_up_calc
set_window_values(integer)
help_window
write_regs
write_reg(integer)
read_next(string)
roll_regs_down(integer)
roll_regs_up(integer)
exchange_1_2
goal
start.
clauses
/* The basic scratchpad memory routines. */
remember(Name,Value):-
asserta(sp(Name,Value)).
forget(Name) :-
retract(sp(Name,_)).
replace(Name,Value):-
retract(sp(Name,_)),
asserta(sp(Name,Value)).
recall(Name,Value) :- sp(Name,Value).
/* The calculator engine */
/* Note the usage of the state variable to control execution.
Taken together, process and action constitute a simple ATN --
Augmented Transition Network. */
start:- forget(state),fail.
start:-
set_up_calc,
write_regs,
remember(state,1),
remember(last_char,0),
process.
process:-
recall(state,State),
State=3,!.
process:-
read_next(Instring),
recall(state,State),
action(State,Instring,""),
process.
read_next(Instring):-
readchar(Inchar),
str_char(Instring,Inchar),
write(Instring).
/* These first few action predicates are responsible for reading in
numeric entries. Entries are terminated by an =, CR, or an
operation. When readchar reads -- where is it reading from?
It is not window One. I'll show you later. */
action(1,String,_):-
str_int(String,No),
No>=0,No<=9,
roll_regs_up(4),
replace("1",No),
write_regs,
replace(state,2),
read_next(Instring),
action(2,Instring,String).
action(2,String,Buffer1):-
str_int(String,No),
No>=0,No<=9,
concat(Buffer1,String,Buffer2),
str_real(Buffer2,Value),
replace("1",Value),
write_reg(1),
read_next(Instring),
action(2,Instring,Buffer2).
/* Decimal Points, anyone? */
action(2,String,Buffer1):-
String=".",
concat(Buffer1,String,Buffer2),
str_real(Buffer2,Value),
replace("1",Value),
write_reg(1),
read_next(Instring),
action(2,Instring,Buffer2).
/* How about elementary operators */
/* (Where is Turbo Prolog's ^ operator? */
action(_,String,_):-
String="+",
recall("1",X),
recall("2",Y),
Z=X+Y,
replace("1",Z),
roll_regs_down(2),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="-",
recall("1",X),
recall("2",Y),
Z=Y-X,
replace("1",Z),
roll_regs_down(2),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="*",
recall("1",X),
recall("2",Y),
Z=X*Y,
replace("1",Z),
roll_regs_down(2),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="/",
recall("1",X),
recall("2",Y),
Z=Y/X,
replace("1",Z),
roll_regs_down(2),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="=",
replace(state,1),!.
action(_,String,_):-
String="\13",
replace(state,1),!.
/* Swaps registers one and two. Handy. */
action(_,String,_):- String="e",exchange_1_2.
action(_,String,_):- String="E",exchange_1_2.
/* Roll registers down. Also provides a Clear Entry Function. */
action(_,String,_):-
String="d",
roll_regs_down(1),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="D",
roll_regs_down(1),
write_regs,
replace(state,1),!.
/* What goes down must come up! */
action(_,String,_):-
String="u",
roll_regs_up(4),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="U",
roll_regs_up(4),
write_regs,
replace(state,1),!.
/* Aha - the function keys
059 ==> F1
060 ==> F2
061 ==> F3, etc. */
/*Problem 1: On my system, I can't trap F3 as written here.
Does it work on your system? Why or Why Not?
Have you noticed that if you use the prompt
statement to redefine function keys in association
with ANSI.SYS in Dos, that Turbo Prolog does not
mask these definitions on entry?
Problem 2: Why does the error indicator beep when a function
key is depressed? */
action(_,String,_):-
String="\59",
/* F1 ==> Sqrt */
recall("1",Value),
NewValue=sqrt(Value),
replace("1",NewValue),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="\60",
/* F2 ==> ln */
recall("1",Value),
NewValue=ln(Value),
replace("1",NewValue),
write_regs,
replace(state,1),!.
action(_,String,_):-
String="\61",
/* F3 ==> exp */
recall("1",Value),
NewValue=exp(Value),
replace("1",NewValue),
write_regs,
replace(state,1),!.
/* The way out */
action(_,String,_):-
String="q",
replace(state,3),!.
action(_,String,_):-
String="Q",
replace(state,3),!.
/* Notify about bad key presses. Also guarantees a true
true evaluation at the end of any action string. */
action(_,_,Buffer):-!,
sound(1,3000),
recall(state,State),
read_next(Instring),
action(State,Instring,Buffer).
/* Looks simple enough */
write_regs:-
write_reg(1),write_reg(2),write_reg(3),write_reg(4).
write_reg(No) :-
str_int(Reg,No),
recall(Reg,Value),
shiftwindow(No),
nl,
write(Value),
shiftwindow(5).
/* What is window 5? Why do we keep going back to it? */
/* Whee!!!! I'm recursive! */
roll_regs_up(0):-
replace("1",0),!.
roll_regs_up(No) :-
str_int(Reg,No),
recall(Reg,Value),
RegUpNo=No+1,
str_int(RegUp,RegUpNo),
replace(RegUp,Value),
NextReg=No-1,
roll_regs_up(NextReg).
/* Big deal. So am I. */
roll_regs_down(5):-!.
roll_regs_down(No) :-
str_int(Reg,No),
RegDnNo=No+1,
str_int(RegDn,RegDnNo),
recall(RegDn,Value),
replace(Reg,Value),
NextReg=No+1,
roll_regs_down(NextReg).
/* No mysteries here. */
exchange_1_2:-
recall("1",X),
recall("2",Y),
replace("1",Y),
replace("2",X),
write_regs,
replace(state,1),!.
/* Defines the calculators windows. Note the attribute definition
of Window 5 */
set_up_calc :-
makewindow(8,17,33,"",0,0,25,80),
makewindow(7,18,33,"Calculator Functions",2,41,14,35),
help_window,
makewindow(6,18,33,"Turbo Prolog Calculator",2,3,16,35),
makewindow(1,33,18,"One",13,6,3,29),
makewindow(2,33,18,"Two",10,6,3,29),
makewindow(3,33,18,"Three",7,6,3,29),
makewindow(4,33,18,"Four",4,6,3,29),
makewindow(5,17,17,"Invisible Window",17,41,3,25),
set_window_values(1),
set_window_values(2),
set_window_values(3),
set_window_values(4),
remember("5",0.00).
set_window_values(No) :-str_int(Reg,No),recall(Reg,_),!.
set_window_values(No) :-str_int(Reg,No),remember(Reg,0).
/* You could make this a pop-up feature. Actually, why not pop up
the calculator in the midst of your program as needed? Are you
ready for the Turbo Desktop Environment? Not that I would
abandon my trusty Sidekick! */
help_window :-
cursor(1,1),write("Operators"),cursor(1,12),write("Function"),
cursor(2,1),write("+ - * /"),cursor(2,12),write("Math Operators"),
cursor(3,1),write("E"),cursor(3,12),write("Exchange 1<-->2"),
cursor(4,1),write("U"),cursor(4,12),write("Roll Registers Up"),
cursor(5,1),write("D"),cursor(5,12),write("Roll Registers Down"),
cursor(6,1),write("Q"),cursor(6,12),write("Quit"),
cursor(8,1),write("F1"),cursor(8,12),write("Square Root"),
cursor(9,1),write("F2"),cursor(9,12),write("Ln One"),
cursor(10,1),write("F3"),cursor(10,12),write("e^One").